/*     */ package blockbuster.math;
/*     */ 
/*     */ import blockbuster.math.functions.Function;
/*     */ import blockbuster.math.functions.classic.Abs;
/*     */ import blockbuster.math.functions.classic.Exp;
/*     */ import blockbuster.math.functions.classic.Ln;
/*     */ import blockbuster.math.functions.classic.Mod;
/*     */ import blockbuster.math.functions.classic.Pow;
/*     */ import blockbuster.math.functions.classic.Sqrt;
/*     */ import blockbuster.math.functions.limit.Clamp;
/*     */ import blockbuster.math.functions.limit.Max;
/*     */ import blockbuster.math.functions.limit.Min;
/*     */ import blockbuster.math.functions.rounding.Ceil;
/*     */ import blockbuster.math.functions.rounding.Floor;
/*     */ import blockbuster.math.functions.rounding.Round;
/*     */ import blockbuster.math.functions.rounding.Trunc;
/*     */ import blockbuster.math.functions.string.StringContains;
/*     */ import blockbuster.math.functions.string.StringEndsWith;
/*     */ import blockbuster.math.functions.string.StringStartsWith;
/*     */ import blockbuster.math.functions.trig.Acos;
/*     */ import blockbuster.math.functions.trig.Asin;
/*     */ import blockbuster.math.functions.trig.Atan;
/*     */ import blockbuster.math.functions.trig.Atan2;
/*     */ import blockbuster.math.functions.trig.Cos;
/*     */ import blockbuster.math.functions.trig.Sin;
/*     */ import blockbuster.math.functions.utility.DieRoll;
/*     */ import blockbuster.math.functions.utility.DieRollInteger;
/*     */ import blockbuster.math.functions.utility.HermiteBlend;
/*     */ import blockbuster.math.functions.utility.Lerp;
/*     */ import blockbuster.math.functions.utility.LerpRotate;
/*     */ import blockbuster.math.functions.utility.Random;
/*     */ import blockbuster.math.functions.utility.RandomInteger;
/*     */ import java.lang.reflect.Constructor;
/*     */ import java.util.ArrayList;
/*     */ import java.util.HashMap;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class MathBuilder
/*     */ {
/*  45 */   public Map<String, Variable> variables = new HashMap<>();
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*  50 */   public Map<String, Class<? extends Function>> functions = new HashMap<>();
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected boolean strict = true;
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public MathBuilder() {
/*  61 */     register(new Variable("PI", Math.PI));
/*  62 */     register(new Variable("E", Math.E));
/*     */ 
/*     */     
/*  65 */     this.functions.put("floor", Floor.class);
/*  66 */     this.functions.put("round", Round.class);
/*  67 */     this.functions.put("ceil", Ceil.class);
/*  68 */     this.functions.put("trunc", Trunc.class);
/*     */ 
/*     */     
/*  71 */     this.functions.put("clamp", Clamp.class);
/*  72 */     this.functions.put("max", Max.class);
/*  73 */     this.functions.put("min", Min.class);
/*     */ 
/*     */     
/*  76 */     this.functions.put("abs", Abs.class);
/*  77 */     this.functions.put("exp", Exp.class);
/*  78 */     this.functions.put("ln", Ln.class);
/*  79 */     this.functions.put("sqrt", Sqrt.class);
/*  80 */     this.functions.put("mod", Mod.class);
/*  81 */     this.functions.put("pow", Pow.class);
/*     */ 
/*     */     
/*  84 */     this.functions.put("cos", Cos.class);
/*  85 */     this.functions.put("sin", Sin.class);
/*  86 */     this.functions.put("acos", Acos.class);
/*  87 */     this.functions.put("asin", Asin.class);
/*  88 */     this.functions.put("atan", Atan.class);
/*  89 */     this.functions.put("atan2", Atan2.class);
/*     */ 
/*     */     
/*  92 */     this.functions.put("lerp", Lerp.class);
/*  93 */     this.functions.put("lerprotate", LerpRotate.class);
/*  94 */     this.functions.put("random", Random.class);
/*  95 */     this.functions.put("randomi", RandomInteger.class);
/*  96 */     this.functions.put("roll", DieRoll.class);
/*  97 */     this.functions.put("rolli", DieRollInteger.class);
/*  98 */     this.functions.put("hermite", HermiteBlend.class);
/*     */ 
/*     */     
/* 101 */     this.functions.put("str_contains", StringContains.class);
/* 102 */     this.functions.put("str_starts", StringStartsWith.class);
/* 103 */     this.functions.put("str_ends", StringEndsWith.class);
/*     */   }
/*     */ 
/*     */   
/*     */   public MathBuilder lenient() {
/* 108 */     this.strict = false;
/*     */     
/* 110 */     return this;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public void register(Variable variable) {
/* 118 */     this.variables.put(variable.getName(), variable);
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public IValue parse(String expression) throws Exception {
/* 127 */     return parseSymbols(breakdownChars(breakdown(expression)));
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public String[] breakdown(String expression) throws Exception {
/* 136 */     if (this.strict && !expression.matches("^[\\w\\d\\s_+-/*%^&|<>=!?:.,()\"'@~\\[\\]]+$"))
/*     */     {
/* 138 */       throw new Exception("Given expression '" + expression + "' contains illegal characters!");
/*     */     }
/*     */     
/* 141 */     String[] chars = expression.split("(?!^)");
/*     */     
/* 143 */     int left = 0;
/* 144 */     int right = 0;
/*     */     
/* 146 */     for (String s : chars) {
/*     */       
/* 148 */       if (s.equals("(")) {
/*     */         
/* 150 */         left++;
/*     */       }
/* 152 */       else if (s.equals(")")) {
/*     */         
/* 154 */         right++;
/*     */       } 
/*     */     } 
/*     */ 
/*     */     
/* 159 */     if (left != right)
/*     */     {
/* 161 */       throw new Exception("Given expression '" + expression + "' has more uneven amount of parenthesis, there are " + left + " open and " + right + " closed!");
/*     */     }
/*     */     
/* 164 */     return chars;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public List<Object> breakdownChars(String[] chars) {
/* 172 */     List<Object> symbols = new ArrayList();
/* 173 */     String buffer = "";
/* 174 */     int len = chars.length;
/* 175 */     boolean string = false;
/*     */     
/* 177 */     for (int i = 0; i < len; i++) {
/*     */       
/* 179 */       String s = chars[i];
/* 180 */       boolean longOperator = (i < chars.length - 1 && isOperator(s + chars[i + 1]));
/*     */       
/* 182 */       if (s.equals("\""))
/*     */       {
/* 184 */         string = !string;
/*     */       }
/*     */       
/* 187 */       if (string) {
/*     */         
/* 189 */         buffer = buffer + s; continue;
/*     */       } 
/* 191 */       if (isOperator(s) || longOperator || s.equals(",")) {
/*     */ 
/*     */ 
/*     */         
/* 195 */         if (s.equals("-")) {
/*     */           
/* 197 */           int size = symbols.size();
/*     */           
/* 199 */           boolean isEmpty = buffer.trim().isEmpty();
/* 200 */           boolean isFirst = (size == 0 && isEmpty);
/* 201 */           boolean isOperatorBehind = (size > 0 && (isOperator(symbols.get(size - 1)) || symbols.get(size - 1).equals(",")) && isEmpty);
/*     */           
/* 203 */           if (isFirst || isOperatorBehind) {
/*     */             
/* 205 */             buffer = buffer + s;
/*     */ 
/*     */             
/*     */             continue;
/*     */           } 
/*     */         } 
/*     */         
/* 212 */         if (!buffer.isEmpty()) {
/*     */           
/* 214 */           symbols.add(buffer);
/* 215 */           buffer = "";
/*     */         } 
/*     */         
/* 218 */         if (longOperator) {
/*     */           
/* 220 */           symbols.add(s + chars[i + 1]);
/* 221 */           i++;
/*     */         }
/*     */         else {
/*     */           
/* 225 */           symbols.add(s);
/*     */         }  continue;
/*     */       } 
/* 228 */       if (s.equals("(")) {
/*     */ 
/*     */         
/* 231 */         if (!buffer.isEmpty()) {
/*     */           
/* 233 */           symbols.add(buffer);
/* 234 */           buffer = "";
/*     */         } 
/*     */         
/* 237 */         int counter = 1;
/*     */         
/* 239 */         for (int j = i + 1; j < len; j++)
/*     */         {
/* 241 */           String c = chars[j];
/*     */           
/* 243 */           if (c.equals("(")) {
/*     */             
/* 245 */             counter++;
/*     */           }
/* 247 */           else if (c.equals(")")) {
/*     */             
/* 249 */             counter--;
/*     */           } 
/*     */           
/* 252 */           if (counter == 0) {
/*     */             
/* 254 */             symbols.add(breakdownChars(buffer.split("(?!^)")));
/*     */             
/* 256 */             i = j;
/* 257 */             buffer = "";
/*     */ 
/*     */             
/*     */             break;
/*     */           } 
/*     */           
/* 263 */           buffer = buffer + c;
/*     */         
/*     */         }
/*     */       
/*     */       }
/*     */       else {
/*     */         
/* 270 */         buffer = buffer + s;
/*     */       } 
/*     */       continue;
/*     */     } 
/* 274 */     if (!buffer.isEmpty())
/*     */     {
/* 276 */       symbols.add(buffer);
/*     */     }
/*     */     
/* 279 */     return trimSymbols(symbols);
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   private List<Object> trimSymbols(List<Object> symbols) {
/* 287 */     List<Object> newSymbols = new ArrayList();
/*     */     
/* 289 */     for (int i = 0; i < symbols.size(); i++) {
/*     */       
/* 291 */       Object value = symbols.get(i);
/*     */       
/* 293 */       if (value instanceof String) {
/*     */         
/* 295 */         String string = ((String)value).trim();
/*     */         
/* 297 */         if (!string.isEmpty())
/*     */         {
/* 299 */           newSymbols.add(string);
/*     */         }
/*     */       }
/*     */       else {
/*     */         
/* 304 */         newSymbols.add(trimSymbols((List<Object>)value));
/*     */       } 
/*     */     } 
/*     */     
/* 308 */     return newSymbols;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public IValue parseSymbols(List<Object> symbols) throws Exception {
/* 325 */     IValue ternary = tryTernary(symbols);
/*     */     
/* 327 */     if (ternary != null)
/*     */     {
/* 329 */       return ternary;
/*     */     }
/*     */     
/* 332 */     int size = symbols.size();
/*     */ 
/*     */     
/* 335 */     if (size == 1)
/*     */     {
/* 337 */       return valueFromObject(symbols.get(0));
/*     */     }
/*     */ 
/*     */     
/* 341 */     if (size == 2) {
/*     */       
/* 343 */       Object first = symbols.get(0);
/* 344 */       Object second = symbols.get(1);
/*     */       
/* 346 */       if ((isVariable(first) || first.equals("-")) && second instanceof List)
/*     */       {
/* 348 */         return createFunction((String)first, (List<Object>)second);
/*     */       }
/*     */     } 
/*     */ 
/*     */     
/* 353 */     int lastOp = seekLastOperator(symbols);
/* 354 */     int op = lastOp;
/*     */     
/* 356 */     while (op != -1) {
/*     */       
/* 358 */       int leftOp = seekLastOperator(symbols, op - 1);
/*     */       
/* 360 */       if (leftOp != -1) {
/*     */         
/* 362 */         Operation left = operationForOperator((String)symbols.get(leftOp));
/* 363 */         Operation right = operationForOperator((String)symbols.get(op));
/*     */         
/* 365 */         if (right.value > left.value) {
/*     */           
/* 367 */           IValue leftValue = parseSymbols(symbols.subList(0, leftOp));
/* 368 */           IValue rightValue = parseSymbols(symbols.subList(leftOp + 1, size));
/*     */           
/* 370 */           return new Operator(left, leftValue, rightValue);
/*     */         } 
/* 372 */         if (left.value > right.value) {
/*     */           
/* 374 */           Operation initial = operationForOperator((String)symbols.get(lastOp));
/*     */           
/* 376 */           if (initial.value < left.value) {
/*     */             
/* 378 */             IValue iValue1 = parseSymbols(symbols.subList(0, lastOp));
/* 379 */             IValue iValue2 = parseSymbols(symbols.subList(lastOp + 1, size));
/*     */             
/* 381 */             return new Operator(initial, iValue1, iValue2);
/*     */           } 
/*     */           
/* 384 */           IValue leftValue = parseSymbols(symbols.subList(0, op));
/* 385 */           IValue rightValue = parseSymbols(symbols.subList(op + 1, size));
/*     */           
/* 387 */           return new Operator(right, leftValue, rightValue);
/*     */         } 
/*     */       } 
/*     */       
/* 391 */       op = leftOp;
/*     */     } 
/*     */     
/* 394 */     Operation operation = operationForOperator((String)symbols.get(lastOp));
/*     */     
/* 396 */     return new Operator(operation, parseSymbols(symbols.subList(0, lastOp)), parseSymbols(symbols.subList(lastOp + 1, size)));
/*     */   }
/*     */ 
/*     */   
/*     */   protected int seekLastOperator(List<Object> symbols) {
/* 401 */     return seekLastOperator(symbols, symbols.size() - 1);
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected int seekLastOperator(List<Object> symbols, int offset) {
/* 409 */     for (int i = offset; i >= 0; i--) {
/*     */       
/* 411 */       Object o = symbols.get(i);
/*     */       
/* 413 */       if (isOperator(o)) {
/*     */ 
/*     */         
/* 416 */         if (o.equals("-")) {
/*     */           
/* 418 */           Object next = (i < symbols.size() - 1) ? symbols.get(i + 1) : null;
/* 419 */           Object prev = (i > 0) ? symbols.get(i - 1) : null;
/*     */           
/* 421 */           if (next instanceof List && (isOperator(prev) || prev == null)) {
/*     */             continue;
/*     */           }
/*     */         } 
/*     */ 
/*     */         
/* 427 */         return i;
/*     */       } 
/*     */       continue;
/*     */     } 
/* 431 */     return -1;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected IValue tryTernary(List<Object> symbols) throws Exception {
/* 443 */     int question = -1;
/* 444 */     int questions = 0;
/* 445 */     int colon = -1;
/* 446 */     int colons = 0;
/* 447 */     int size = symbols.size();
/*     */     
/* 449 */     for (int i = 0; i < size; i++) {
/*     */       
/* 451 */       Object object = symbols.get(i);
/*     */       
/* 453 */       if (object instanceof String)
/*     */       {
/* 455 */         if (object.equals("?")) {
/*     */           
/* 457 */           if (question == -1)
/*     */           {
/* 459 */             question = i;
/*     */           }
/*     */           
/* 462 */           questions++;
/*     */         }
/* 464 */         else if (object.equals(":")) {
/*     */           
/* 466 */           if (colons + 1 == questions && colon == -1)
/*     */           {
/* 468 */             colon = i;
/*     */           }
/*     */           
/* 471 */           colons++;
/*     */         } 
/*     */       }
/*     */     } 
/*     */     
/* 476 */     if (questions == colons && question > 0 && question + 1 < colon && colon < size - 1)
/*     */     {
/* 478 */       return new Ternary(
/* 479 */           parseSymbols(symbols.subList(0, question)), 
/* 480 */           parseSymbols(symbols.subList(question + 1, colon)), 
/* 481 */           parseSymbols(symbols.subList(colon + 1, size)));
/*     */     }
/*     */ 
/*     */     
/* 485 */     return null;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected IValue createFunction(String first, List<Object> args) throws Exception {
/* 502 */     if (first.equals("!"))
/*     */     {
/* 504 */       return new Negate(parseSymbols(args));
/*     */     }
/*     */     
/* 507 */     if (first.startsWith("!") && first.length() > 1)
/*     */     {
/* 509 */       return new Negate(createFunction(first.substring(1), args));
/*     */     }
/*     */ 
/*     */     
/* 513 */     if (first.equals("-"))
/*     */     {
/* 515 */       return new Negative(parseSymbols(args));
/*     */     }
/*     */     
/* 518 */     if (first.startsWith("-") && first.length() > 1)
/*     */     {
/* 520 */       return new Negative(createFunction(first.substring(1), args));
/*     */     }
/*     */     
/* 523 */     if (!this.functions.containsKey(first))
/*     */     {
/* 525 */       throw new Exception("Function '" + first + "' couldn't be found!");
/*     */     }
/*     */     
/* 528 */     List<IValue> values = new ArrayList<>();
/* 529 */     List<Object> buffer = new ArrayList();
/*     */     
/* 531 */     for (Object o : args) {
/*     */       
/* 533 */       if (o.equals(",")) {
/*     */         
/* 535 */         values.add(parseSymbols(buffer));
/* 536 */         buffer.clear();
/*     */         
/*     */         continue;
/*     */       } 
/* 540 */       buffer.add(o);
/*     */     } 
/*     */ 
/*     */     
/* 544 */     if (!buffer.isEmpty())
/*     */     {
/* 546 */       values.add(parseSymbols(buffer));
/*     */     }
/*     */     
/* 549 */     Class<? extends Function> function = this.functions.get(first);
/* 550 */     Constructor<? extends Function> ctor = function.getConstructor(new Class[] { IValue[].class, String.class });
/* 551 */     Function func = ctor.newInstance(new Object[] { values.toArray(new IValue[values.size()]), first });
/*     */     
/* 553 */     return (IValue)func;
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   public IValue valueFromObject(Object object) throws Exception {
/* 566 */     if (object instanceof String) {
/*     */       
/* 568 */       String symbol = (String)object;
/*     */ 
/*     */       
/* 571 */       if (symbol.startsWith("!"))
/*     */       {
/* 573 */         return new Negate(valueFromObject(symbol.substring(1)));
/*     */       }
/*     */       
/* 576 */       if (symbol.startsWith("\"") && symbol.endsWith("\""))
/*     */       {
/* 578 */         return new Constant(symbol.substring(1, symbol.length() - 1));
/*     */       }
/*     */       
/* 581 */       if (isDecimal(symbol))
/*     */       {
/* 583 */         return new Constant(Double.parseDouble(symbol));
/*     */       }
/* 585 */       if (isVariable(symbol))
/*     */       {
/*     */         
/* 588 */         if (symbol.startsWith("-"))
/*     */         {
/* 590 */           symbol = symbol.substring(1);
/* 591 */           Variable value = getVariable(symbol);
/*     */           
/* 593 */           if (value != null)
/*     */           {
/* 595 */             return new Negative(value);
/*     */           }
/*     */         }
/*     */         else
/*     */         {
/* 600 */           IValue value = getVariable(symbol);
/*     */ 
/*     */           
/* 603 */           if (value != null)
/*     */           {
/* 605 */             return value;
/*     */           }
/*     */         }
/*     */       
/*     */       }
/* 610 */     } else if (object instanceof List) {
/*     */       
/* 612 */       return new Group(parseSymbols((List<Object>)object));
/*     */     } 
/*     */     
/* 615 */     throw new Exception("Given object couldn't be converted to value! " + object);
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected Variable getVariable(String name) {
/* 623 */     return this.variables.get(name);
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected Operation operationForOperator(String op) throws Exception {
/* 631 */     for (Operation operation : Operation.values()) {
/*     */       
/* 633 */       if (operation.sign.equals(op))
/*     */       {
/* 635 */         return operation;
/*     */       }
/*     */     } 
/*     */     
/* 639 */     throw new Exception("There is no such operator '" + op + "'!");
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected boolean isVariable(Object o) {
/* 647 */     return (o instanceof String && !isDecimal((String)o) && !isOperator((String)o));
/*     */   }
/*     */ 
/*     */   
/*     */   protected boolean isOperator(Object o) {
/* 652 */     return (o instanceof String && isOperator((String)o));
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected boolean isOperator(String s) {
/* 660 */     return (Operation.OPERATORS.contains(s) || s.equals("?") || s.equals(":"));
/*     */   }
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   
/*     */   protected boolean isDecimal(String s) {
/* 669 */     return s.matches("^-?\\d+(\\.\\d+)?$");
/*     */   }
/*     */ }


/* Location:              D:\fanbian\[D][龙之核心]DragonCore-2.6.0.3.jar!\blockbuster\math\MathBuilder.class
 * Java compiler version: 8 (52.0)
 * JD-Core Version:       1.1.3
 */